<?php


namespace App\Job;


use App\Config\CacheConfig;
use App\Config\QueueConfig;
use App\Enum\AccountNettingEnum;
use App\Http\Library\Lock;
use App\Http\Library\Pfs;
use App\Http\Library\Queue;
use App\Http\Model\Job\PfsHeadQueryWithdrawProvisionModel;
use App\Http\Model\Job\PfsHeadWithdrawProvisionModel;
use App\Http\ModelDao\Job\PfsHeadWithdrawProvisionDao;

class PfsHeadWithdrawProvisionJob
{

    /**
     * 备份金退费借回   机构端 -> 招行
     *
     * @param array $data
     *
     * @throws \Exception
     */
    public static function main(array $data)
    {
        $result = [];
        try {
            /*串行锁-key*/
            $lock = CacheConfig::PFS_HEAD_WITHDRAWPROVISION . ':' . $data['pfs_dw_id'];
            /*串行化处理*/
            if (Lock::lock($lock, 0) === false) {
                /*10s后再次调用*/
                Queue::clock($data, 10);
                return log_arr([
                    '[备份金退费借回-异常]',
                    'msg'    => '没有拿到串行锁',
                    'data'   => serialize($data),
                    'result' => $result,
                ], 'pfs');
            }
            /*提款说明*/
            $data['apply_reason'] = isset($data['apply_reason']) ? $data['apply_reason'] : '退款拨付';
            /*提款类型: 00 备份金、01 其他*/
            $data['apply_type'] = isset($data['apply_type']) ? $data['apply_type'] : '00';
            /*查询推送记录是否已存在*/
            $exist = PfsHeadWithdrawProvisionModel::exist($data);
            /*如果是推送中OR推送成功,则直接跳过处理*/
            if (!empty($exist) && in_array($exist->result, [
                    AccountNettingEnum::RESULT_SUCCESS,
                    AccountNettingEnum::RESULT_ING,
                    AccountNettingEnum::RESULT_WAIT,
                    AccountNettingEnum::RESULT_UNKNOW,
                ])) {
                /*释放锁*/
                Lock::unlock($lock);
                return log_arr([
                    '[备份金退费借回-异常]',
                    'msg'    => '当前记录已经推送过了',
                    'data'   => serialize($data),
                    'result' => $result,
                ], 'pfs');
            }
            /*如果是手动触发的指定额度调用，则跳过检查*/
            if (empty($data['origin']) || $data['origin'] !== 'people') {
                /*
                 * 查询监管账户数据是否全部推送成功
                 * 只有当前监管账户及当前日期下 所有班级汇总信息推送成功,不存在推送失败数据的情况,才允许调用备份金接口
                 * */
                if (PfsHeadQueryWithdrawProvisionModel::payResultHistorySuccess($data['pfs_dw_id'], $data['create_date']) !== true) {
                    log_arr([
                        '备份金退费借回-异常',
                        'msg:当日推送缴退费汇总表PayClassList存在推送失败数据(所有班级汇总信息推送成功,不存在推送失败数据的情况,才允许调用备份金接口)',
                        'data' => $data,
                    ], 'pfs');
                    /*十分钟后再次调用*/
                    Queue::clock($data, 600);
                    return 0;
                }
                /*如果本次备份金不是通过此脚本发起的,则重新计算轧差金额*/
                if (empty($data['origin']) || $data['origin'] !== QueueConfig::PFS_HEAD_WITHDRAWPROVISION) {
                    /*避免频繁调用,设置同一账户10秒间隔*/
                    if (Lock::lock(CacheConfig::CLASS_NETTING . ':' . "{$data['pfs_dw_id']}_{$data['create_date']}", 0)) {
                        Queue::rpush([
                            'pfs_dw_id'   => $data['pfs_dw_id'],
                            'create_date' => $data['create_date'],
                            'origin'      => QueueConfig::PFS_HEAD_WITHDRAWPROVISION,
                        ], QueueConfig::CLASS_NETTING);
                    }
                    /*释放锁*/
                    Lock::unlock($lock);
                    return 0;
                }
            }
            /*轧差金额检查*/
            if (bccomp($data['account_netting'], 0) !== -1) {
                throw new \Exception('招行轧差金额调用,申请轧差金额不是负数!!!');
            }
            /*提款申请编号*/
            if (empty($exist->transfer_id)) {
                $data['transfer_id'] = PfsHeadWithdrawProvisionDao::transferId();
            } else {
                $data['transfer_id'] = $exist->transfer_id;
            }
            /*查询账号主体账号信息*/
            $pfs = PfsHeadWithdrawProvisionModel::pfs($data['pfs_dw_id']);
            /*更新记录状态为推送中*/
            $exist = PfsHeadWithdrawProvisionModel::push($data, $exist, $pfs);

            /*如果当前调用不是人为发起的，则不推送*/
            if ($data['origin'] !== 'people') {
                /*----------------关闭备份金推送*/
                PfsHeadWithdrawProvisionModel::close($exist);
                /*释放锁*/
                return Lock::unlock($lock);
                /*----------------关闭备份金推送*/
            }

            /*
             * 申请提款金额 = 当日轧差额*100*-1
             * */
            $applyAmt = bcmul($data['account_netting'], '-1');
            /*推送招行*/
            $result = Pfs::pfsHeadWithdrawProvision([
                /*机构编号，由招行分配*/
                'agencyId'    => $pfs->pfs_agencyid,
                /*提款申请编号*/
                'transferId'  => $data['transfer_id'],
                /*申请提款金额*/
                'applyAmt'    => $applyAmt,
                /*提款说明*/
                'applyReason' => $data['apply_reason'],
                /*提款类型: 00 备份金、01 其他*/
                'applyType'   => $data['apply_type'],
            ], [
                /*招行-加密密钥*/
                'pfs_encrypt_private' => $pfs->pfs_encrypt_private,
                /*招行-签名密钥*/
                'pfs_sign_private'    => $pfs->pfs_sign_private,
            ]);
            /*刷新数据库同步结果*/
            PfsHeadWithdrawProvisionModel::success($data, $result, $exist);
        } catch (\Exception $exception) {
            log_arr([
                '[备份金退费借回-异常]',
                'line'   => $exception->getLine(),
                'file'   => $exception->getFile(),
                'msg'    => $exception->getMessage(),
                'data'   => serialize($data),
                'result' => $result,
            ], 'pfs');
            /*刷新数据库同步结果*/
            if (!empty($exist) && !in_array($exist->result, [
                    AccountNettingEnum::RESULT_SUCCESS,
                    AccountNettingEnum::RESULT_ING,
                ])) {
                /*刷新同步记录结果为失败*/
                PfsHeadWithdrawProvisionModel::failure($exist, $exception->getMessage());
            }
            throw new \Exception($exception->getMessage());
        }
        /*释放锁*/
        Lock::unlock($lock);
    }

}





/**
 * PfsHeadWithdrawProvisionJob.php
 *
 * 说明:
 *
 * 修改历史
 * ----------------------------------------
 * 2021/6/9 10:06:00   操作:创建
 **/
